﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;

namespace B2BCore
{
    /// <summary>
    /// User Manager Class
    /// </summary>
    public class UserManager
    {
        /// <summary>
        /// The list which keep track of all users
        /// </summary>
        private readonly List<User> _users;

        /// <summary>
        /// Initiates usermanager by creating the users list
        /// </summary>
        public UserManager()
        {
            _users = new List<User>();
        }

        /// <summary>
        /// Get a list of all users
        /// </summary>
        public List<User> GetUsers()
        {
            return _users;
        }

        /// <summary>
        /// Add a new user to the manager list.
        /// </summary>
        /// <param name="username">The name of the user to add.</param>
        /// <param name="socket">The socket of the user.</param>
        /// <param name="ipAddress">The IP Address of the user to add.</param>
        public void AddUser(string username, Socket socket, string ipAddress)
        {
            if (socket == null)
                throw new ArgumentNullException(Utilities.GetVariableName(socket));
            if (String.IsNullOrEmpty(username))
                throw new ArgumentException(ErrorStrings.ExMsgUserNameNullOrEmpty, Utilities.GetVariableName(username));
            if (String.IsNullOrEmpty(ipAddress))
                throw new ArgumentNullException(Utilities.GetVariableName(ipAddress), ErrorStrings.ExMsgIpAddressNull);

            _users.Add(new User(username, socket, ipAddress));
        }

        /// <summary>
        /// Add a new user to the manager list.
        /// </summary>
        /// <param name="username">The name of the user to add.</param>
        /// <param name="socket">The socket of the user.</param>
        /// <param name="ipAddress">The IP Address of the user to add.</param>
        public void AddUser(string username, Socket socket, System.Net.IPAddress ipAddress)
        {
            if (socket == null)
                throw new ArgumentNullException(Utilities.GetVariableName(socket));
            if (String.IsNullOrEmpty(username))
                throw new ArgumentException(ErrorStrings.ExMsgUserNameNullOrEmpty, Utilities.GetVariableName(username));
            if (ipAddress == null)
                throw new ArgumentNullException(Utilities.GetVariableName(ipAddress), ErrorStrings.ExMsgIpAddressNull);

            _users.Add(new User(username, socket, ipAddress));
        }

        /// <summary>
        /// Add a new user to the manager list.
        /// </summary>
        /// <param name="username">The name of the user to add.</param>
        /// <param name="socket">The socket of the user.</param>
        public void AddUser(string username, Socket socket)
        {
            if (socket == null)
                throw new ArgumentNullException(Utilities.GetVariableName(socket));
            if (String.IsNullOrEmpty(username))
                throw new ArgumentException(ErrorStrings.ExMsgUserNameNullOrEmpty, Utilities.GetVariableName(username));

            AddUser(username, socket, System.Net.IPAddress.None);
        }

        /// <summary>
        /// Remove a user from the manager list by their username.
        /// </summary>
        /// <param name="username">The name of the user to remove.</param>
        public bool RemoveUser(string username)
        {
            if (String.IsNullOrEmpty(username))
                throw new ArgumentException(ErrorStrings.ExMsgUserNameNullOrEmpty, Utilities.GetVariableName(username));

            User foundUser = FindUser(username);

            if (foundUser == null)
                return false;

            if (!_users.Remove(foundUser))
                return false;

            return true;
        }

        /// <summary>
        /// Remove a user from the manager list by their IP Address.
        /// </summary>
        /// <param name="ipAddress">The IP Address of the user to remove.</param>
        public bool RemoveUser(System.Net.IPAddress ipAddress)
        {
            if (ipAddress == null)
                throw new ArgumentNullException(Utilities.GetVariableName(ipAddress), ErrorStrings.ExMsgIpAddressNull);

            User foundUser = FindUser(ipAddress);

            if (foundUser != null)
            {
                if (!_users.Remove(foundUser))
                    return false;

                return true;
            }

            return false;
        }

        /// <summary>
        /// Find a user by their username.
        /// </summary>
        /// <param name="username">The name of the user to find.</param>
        /// <returns>A valid user if found</returns>
        public User FindUser(string username)
        {
            if (String.IsNullOrEmpty(username))
                throw new ArgumentException(ErrorStrings.ExMsgUserNameNullOrEmpty, Utilities.GetVariableName(username));

            return _users.Find(u => u.Name == username);
        }


        /// <summary>
        /// Find a user by their IP Address.
        /// </summary>
        /// <param name="ipAddress">The IP Address of the user to find.</param>
        /// <returns>A valid user if found</returns>
        public User FindUser(System.Net.IPAddress ipAddress)
        {
            if (ipAddress == null)
                throw new ArgumentNullException(Utilities.GetVariableName(ipAddress), ErrorStrings.ExMsgIpAddressNull);

            return _users.Find(u => u.IpAddress.Equals(ipAddress));
        }
    }
}
